/*
 * @Description: 注册所有服务
 * @Autor: HuiSir<273250950@qq.com>
 * @Date: 2022-04-22 10:41:24
 * @LastEditTime: 2022-07-07 19:38:05
 */
import {
    useRedisPool,
    useResult,
    useClassDecorators,
    useMethodDecorators,
    useParameterDecorators
} from 'tcp-micro-service'
import CONST from '../constant/index.js'
import { SaveDto, FindDto } from './Dto/index.js'

const { Controller } = useClassDecorators()
const { Sys, Bind } = useMethodDecorators()
const { Body, Params } = useParameterDecorators()
const { succ, fail } = useResult()

// redis连接池
const redisPool = useRedisPool()

@Controller()
export default class Register {
    /**
     * 存储服务信息
     */
    @Sys()
    @Bind(SaveDto)
    async save(@Body() server: SaveDto) {

        // 存redis
        // 这里无需判断服务是否已注册，直接覆盖就可
        // 需要判断服务端口是否被占用（判断host和port是否有一致的，这里只是简单判断，无法深究不同host是否指向同一ip）

        // 查所有
        const redisConn = await redisPool.getConn()
        const serviceList = await redisConn.hgetall(CONST.KEY_SERVICE_REG)
        // 遍历所有缓存的服务数据
        for (let serviceName in serviceList) {
            const { host, port } = JSON.parse(serviceList[serviceName])

            // 判断服务端口是否被占用
            if (server.name !== serviceName && server.host === host && server.port === port) {
                redisConn.release()  // 释放redis
                return fail(`端口 ${port} 已被占用！`)
            }
        }

        // 存表
        await redisConn.hmset(CONST.KEY_SERVICE_REG, { [server.name]: JSON.stringify(server) })

        // 释放
        redisConn.release()

        return succ(`服务 ${server.name} 注册成功！`)
    }

    /**
     * 查询单个服务数据
     * 需要传微服务名称（主路由）
     */
    @Sys('/:name')
    @Bind(FindDto)
    async find(@Params('name') name: FindDto['name']) {
        const redisConn = await redisPool.getConn()
        const service = await redisConn.hget(CONST.KEY_SERVICE_REG, name)
        // 释放
        redisConn.release()
        const data = JSON.parse(service)
        if (data) {
            return succ({ data: JSON.parse(service) })
        } else {
            return fail('找不到此服务或此服务未注册！')
        }
    }
}